package com.example.springbootthreadexamples.config;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

import com.alibaba.ttl.threadpool.TtlExecutors;
import com.example.springbootthreadexamples.thread.BizContextTaskDecorator;
import org.springframework.context.annotation.Bean;
import org.springframework.core.task.TaskDecorator;

import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;

/**
 * @author LanWP
 * @date 2024-08-02
 */
@Configuration
public class ThreadPoolConfig {

//    private static final int CORE_POOL_SIZE = 10;
    private static final int CORE_POOL_SIZE = Runtime.getRuntime().availableProcessors() +1; // 20
    private static final int MAX_POOL_SIZE = Runtime.getRuntime().availableProcessors() * 2 +1; // 100
    private static final int KEEP_ALIVE_SECONDS = 60;

    /**
     * TaskExecutor ， 用来执行异步任务, spring 默认的 SimpleAsyncTaskExecutor， 如果有配置实例名称使用 taskExcutor
     *
     * Spring2自带的线程池 SimpleAsyncTaskExecutor-15-2024-08-04 19:37:25
     * 默认线程池 beanName taskExecutor , 如果方法名或实例名改成其他名字，spring 会创建一个 SimpleAsyncTaskExecutor 的 bean 作为默认线程池
     *
     *
     * TransmittableThreadLocal是阿里巴巴开源的一个框架，用于解决在使用线程池等场景下，ThreadLocal变量无法跨线程传递的问题。能够在多线程传递中保持变量的传递性，确保在父线程和子线程之间正确传递ThreadLocal变量。
     *
     * 简单的来说就是：ThreadLocal适用于线程内部的数据存储和访问，确保数据在线程间的隔离。InheritableThreadLocal适用于需要在父线程和子线程间传递数据的场景，实现数据的继承。TransmittableThreadLocal则是为了解决在使用线程池等场景下，ThreadLocal变量无法跨线程传递的问题，实现数据的跨线程传递。
     */
    @Bean
    public Executor taskExecutorSpringThreadPoolTaskExecutor() {
//    public Executor taskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(CORE_POOL_SIZE); // 默认线程数
        executor.setMaxPoolSize(MAX_POOL_SIZE); // 最大线程数
        executor.setKeepAliveSeconds(KEEP_ALIVE_SECONDS); // 允许线程空闲时间（单位：默认为秒）
        executor.setQueueCapacity(1000); // 缓冲队列大小
        // BizContextTaskDecorator 复制线程变量
        executor.setTaskDecorator(new BizContextTaskDecorator()); // 需要复制线程变量时使用
        executor.setThreadNamePrefix("task-thread-"); // 线程池名前缀
        // 线程池对拒绝任务的处理策略：
        // AbortPolicy 直接中断执行， 默认策略
        // executor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());
        // CallerRunsPolicy：由调用线程（提交任务的线程）处理该任务
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        executor.initialize(); // 可选
        return executor;
    }

    /**
     * 阿里：TransmittableThreadLocal
     * TransmittableThreadLocal就是为了解决线程池之间ThreadLocal本地变量传递的问题。\
     *
     * 解决线程池本地变量问题，TransmittableThreadLocal详解 （InheritableThreadLocal详解 https://blog.csdn.net/qq_14946371/article/details/129321109）
     *
     * @return
     */
    @Bean
    public Executor taskExecutor() {
        int corePoolSize = 20;
        int maxPoolSize = 200;
        long keepAliveSeconds = 60L;

        // 自定义线程池中线程名前缀
        String namePrefix = "ttl-task-thread-"; // 线程池名前缀
        ThreadFactory namedThreadFactory = new ThreadFactory() {
            private final AtomicInteger threadCount = new AtomicInteger();
            @Override
            public Thread newThread(Runnable r) {
                Thread t = new Thread(r, namePrefix + threadCount.getAndIncrement());
                // 可以在这里设置线程的其他属性，例如优先级，是否为守护线程等
                return t;
            }
        };
//        new ThreadPoolExecutor(20, 200, 60000L, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<>(1000))
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
                corePoolSize,
                maxPoolSize,
                keepAliveSeconds,
                TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(1000),
                namedThreadFactory);

        // ExecutorService 为 Executor 子类
        ExecutorService ttlExecutorService = TtlExecutors.getTtlExecutorService(threadPoolExecutor);
        return ttlExecutorService;


    }

    /* TaskScheduler ， 用来执行异步调度任务,taskScheduler， 用来执行异步调度任务
    @Bean
    public TaskScheduler taskScheduler() {
        ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
        scheduler.setPoolSize(10);
        scheduler.initialize();
        return scheduler;
    }*/
}
